package com.cci.kangdao.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cci.kangdao.aop.UserThreadLocal;
import com.cci.kangdao.crmapi.CRMApiUtils;
import com.cci.kangdao.crmapi.CRMResponeEntity;
import com.cci.kangdao.dao.*;
import com.cci.kangdao.dao.model.*;
import com.cci.kangdao.dto.BaseResponse;
import com.cci.kangdao.redis.RedisClientUtils;
import com.cci.kangdao.service.NoticeService;
import com.cci.kangdao.service.OutRangeTService;
import com.cci.kangdao.service.PropertiesUtils;
import com.cci.kangdao.service.WorkOrderTService;
import com.cci.kangdao.utilTool.Dictionaries;
import com.cci.kangdao.utilTool.GetDistance;
import com.cci.kangdao.utilTool.LocalTimeUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service("outRangeTService")
public class OutRangeTServiceImpl implements OutRangeTService {

	@Autowired
	private WorkOrderTDao workOrderTDao;
	@Autowired
	private DictionariesTDao dictionariesTDao;
	@Autowired
	private OutRangeTDao outRangeTDao;
	@Autowired
	private OutRangeFlowDao outRangeFlowDao;
	@Autowired
	private OutRangePrincipalDao outRangePrincipalDao;
	@Autowired
	private UserTDao userTDao;
	@Resource
	private PropertiesUtils propertiesUtils;
	@Autowired
	private PositionUserTDao positionUserTDao;
	@Autowired
	private WorkOrderTService workOrderTService;
	@Autowired
	private WorkOrderPicsDao workOrderPicsDao;
	@Resource
	private ServiceStationDao serviceStationDao;
	@Autowired
	private UploadPicturesDao uploadPicturesDao;
	@Autowired
	private CRMPlatformServiceDao platformServiceDao;
	@Autowired
	private RedisClientUtils redisClientUtils;
	@Autowired
	private CompanyTDao companyTDao;
	@Resource
	private NoticeService noticeService;
	@Resource
	private WorkOrderRepairDao workOrderRepairDao;

	@Override
	@Transactional
	public BaseResponse submitOutRangeApply(JSONObject param) {
		BaseResponse checkResult = checkBeforeSubmitOutRangeApply(param);
		if (!checkResult.isSuccess()) {
			return checkResult;
		}
		UserT userT = UserThreadLocal.get();
//		1、插入：超范围服务申请表、超范围服务申请操作记录表、超范围服务负责人表
		OutRangeT outRangeT = new OutRangeT();
		Long orderId = param.getLong("orderId");// 工单id
		Long causeId = param.getLong("causeId");// 原因枚举Id
		String otherRemark = param.getString("otherRemark");// 其他原因说明（其他原因时必须）
		String pics = param.getJSONArray("pics").toJSONString();// 照片地址数组
		double outDistance = param.getDoubleValue("outDistance");
		outRangeT.setOrderId(orderId);
		outRangeT.setCauseId(causeId);
		outRangeT.setOtherRemark(otherRemark);
		outRangeT.setStatus(10);// 申请状态标记10、待一网站长审核20、待区域经理审核30、终审通过40、一网站长审核不通过50、区域经理审核不通过
		outRangeT.setPicUrls(pics);
		outRangeT.setVersion(0);
		outRangeT.setFlag(0);
		outRangeT.setCreator(userT.getId());
		outRangeT.setCreateTime(LocalTimeUtil.getRealCurrentTime());
		outRangeT.setOutDistance(outDistance);
		outRangeTDao.insertSelective(outRangeT);
		OutRangeFlow outRangeFlow = new OutRangeFlow();
		outRangeFlow.setOutRangeId(outRangeT.getId());// 超范围服务申请表ID
		outRangeFlow.setAction(1);// 行为动作1、提交申请2、审批通过3、审批不通过
		outRangeFlow.setNextStatus(10);// 操作后的申请状态标记
		outRangeFlow.setFlag(0);
		outRangeFlow.setCreator(userT.getId());
		outRangeFlow.setCreateTime(LocalTimeUtil.getRealCurrentTime());
		outRangeFlowDao.insertSelective(outRangeFlow);
		// 提交申请后由一网站长初审、服务经理复审
		// 根据工单的服务站点以及渠道，找一网的站长
		WorkOrderT workOrder = workOrderTDao.getWorkOrderByOrderId(orderId);
		List<UserT> stationMangers = userTDao.getStationMangerListByChildSSId(workOrder.getServiceStationId());
		if (CollectionUtils.isEmpty(stationMangers)) {
			stationMangers = userTDao.getStationMasterByWorkOrderId(orderId);
		}
		for (UserT manager : stationMangers) {
			OutRangePrincipal outRangePrincipal = new OutRangePrincipal();
			outRangePrincipal.setOrderId(orderId);// 工单ID
			outRangePrincipal.setOutRangeId(outRangeT.getId());// 超范围服务申请表ID
			outRangePrincipal.setOutRangeStatus(10);// 申请状态标记10、待一网站长审核20、待区域经理审核30、终审通过40、一网站长审核不通过50、区域经理审核不通过
			outRangePrincipal.setPrincipalId(manager.getId());// 负责人Id
			outRangePrincipal.setFlag(0);
			outRangePrincipal.setCreator(userT.getId());
			outRangePrincipal.setCreateTime(LocalTimeUtil.getRealCurrentTime());
			outRangePrincipalDao.insertSelective(outRangePrincipal);
			// 申请通过给一网站长发送短信提醒
			String smsText = "您有新的超距离审批提醒，工单号：%s，正在等待站长审批";
			// 'Function',28,'电子围栏申请状态变更提醒'
			// 'Category',6,'提交申请提醒'
			// 'Category',7,'审批通过提醒'
			// 'Category',8,'审批拒绝提醒'
			// 'Category',9,'已失效提醒'
			noticeService.sendSMS(28, 6, orderId, manager.getId(), manager.getPhone(),
					String.format(smsText, workOrder.getOrderNo()), userT.getId());
		}
		// 工单状态改为 电子围栏审批中。并同步状态
		workOrder.setOrderStatus(38);// 38 电子围栏审批中
		workOrder.setUpdator(userT.getId());
		workOrder.setUpdateTime(LocalTimeUtil.getRealCurrentTime());
		workOrderTDao.updateWorkOrderById(workOrder);
		WorkOrderPics pic = workOrderPicsDao.selectOneByOrderId(workOrder.getId());
		// 插入并保存工单操作记录表数据
		Map<String, Object> workOrderFlowTMap = new HashMap<String, Object>(); // 新建工单操作记录对象
		workOrderFlowTMap.put("OrderId", workOrder.getId());
		workOrderFlowTMap.put("ProcessorId", userT.getId());
		workOrderFlowTMap.put("OrderStatus", workOrder.getOrderStatus());
		workOrderFlowTMap.put("ProcessComment", "");
		workOrderFlowTMap.put("ProLocLon", pic.getLocLon());
		workOrderFlowTMap.put("ProLocLat", pic.getLocLat());
		workOrderFlowTMap.put("ProLocation", pic.getLocation());
		workOrderFlowTMap.put("IMEI", pic.getIMEI()); // 手机串号
		workOrderFlowTMap.put("Flag", 0);
		workOrderFlowTMap.put("Creator", userT.getId());
		workOrderFlowTMap.put("CreateTime", LocalTimeUtil.getRealCurrentTime());
		workOrderRepairDao.saveOperation(workOrderFlowTMap); // 插入并保存工单操作记录数据
		syncOrderStatusToCrm(workOrder);
		return BaseResponse.success();
	}

	// 保存工单的操作日志，同步工单最新状态到crm
	private void syncOrderStatusToCrm(WorkOrderT workOrderT) {
		WorkOrderPics pic = workOrderPicsDao.selectOneByOrderId(workOrderT.getId());
		UserT loginUserT = UserThreadLocal.get();
		// 把关闭工单的信息详情同步到CRM
		Map<String, Object> parameters = new HashMap<String, Object>();
		parameters.put("orderNo", workOrderT.getOrderNo());
		parameters.put("billStatus", workOrderT.getOrderStatus());
		parameters.put("actionTime", LocalTimeUtil.getRealCurrentTime());
		parameters.put("directorName", loginUserT.getContact());
		parameters.put("directorPhone", loginUserT.getPhone());
//		parameters.put("refuseReason", closeReason);
		parameters.put("phoneIMEI", pic.getIMEI());
		parameters.put("positionLat", pic.getLocLat() + "");
		parameters.put("positionLon", pic.getLocLon() + "");
		parameters.put("location", pic.getLocation());
		parameters.put("CCSSComplainerOrderNo", workOrderT.getOrderNoCrm());
		parameters.put("CCSSOrderNo", workOrderT.getCCSSOrderNo());
		parameters.put("customerName", workOrderT.getCustomerName());
		parameters.put("customerPhone", workOrderT.getCustomerPhone());
		parameters.put("customerCompany", workOrderT.getCustomerCompanyName());
		parameters.put("faultDesc", workOrderT.getCustomerComplaint());
		Map<String, Object> sSRepair = serviceStationDao.getStationNoAndNameByStationIdAndCompanyId(
				workOrderT.getServiceStationId(), workOrderT.getOrderChannel());
		if (org.apache.commons.collections.MapUtils.isNotEmpty(sSRepair)) {
			parameters.put("stationNo", sSRepair.get("BusinessNo"));
			parameters.put("stationName", sSRepair.get("StationName"));
		} else {
			parameters.put("stationNo", "");
			parameters.put("stationName", "");
		}
		try {
			CRMResponeEntity cRMResponeEntity = CRMApiUtils.getCRMServiceApi().syncOrderStatusToCrm(
					companyTDao.getCompanyInfoByCompanyID(workOrderT.getOrderChannel()).getCompanyNo(),
					platformServiceDao, redisClientUtils, parameters,null);
			if (cRMResponeEntity.getStatus() != 0) {
				log.error("同步工单状态至CRM失败!状态:" + cRMResponeEntity.getStatus() + ",错误信息:" + cRMResponeEntity.getMessage());
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error("同步工单状态至CRM失败!错误信息:" + e.getMessage(), e);
		}
	}

	private BaseResponse checkBeforeSubmitOutRangeApply(JSONObject param) {
		if (!param.containsKey("orderId") || !param.containsKey("causeId")) {
			return BaseResponse.error("缺少必要参数！");
		}
		Long orderId = param.getLong("orderId");// 工单id
//		1、插入：超范围服务申请表、超范围服务申请操作记录表、超范围服务负责人表
//		2、后台控制当前工单状态、是否已经存在申请
		WorkOrderT workOrder = workOrderTDao.getWorkOrderByOrderId(orderId);
		if (workOrder == null) {
			return BaseResponse.error("未找到该工单信息！");
		}
		int orderStatus = workOrder.getOrderStatus();// OrderStatus>=8技师已接单
		if (orderStatus != 8) {
			return BaseResponse.error("请核实该工单的状态。处于[技师已接单]状态的工单可以进行超距离服务申请！");
		}
		OutRangeT outRangeT = outRangeTDao.getOutRangeTByOrderId(workOrder.getId());
		if (outRangeT != null) {
			return BaseResponse.error("该工单已存在超距离服务申请，请勿重复申请！");
		}
		String causeId = param.getString("causeId");// 原因枚举Id
		String otherRemark = param.getString("otherRemark");// 其他原因说明（其他原因时必须）
//		String pics = param.getJSONArray("pics").toJSONString();// 照片地址数组
		if (workOrder.getIsOutside() == 1) {
			return BaseResponse.error("站外单无需发起超距离服务申请！");
		}
		// DCEC的站内单判断距离是否超限
		double serviceScope = Double.valueOf(dictionariesTDao.getDictionariesListByDTableName("ServiceScope").get(0)
				.getOrDefault("DValue", "0").toString());
		ServiceStationT serviceStation = serviceStationDao.getSSById(workOrder.getServiceStationId());
		String positionLat = serviceStation.getPositionLat();
		String positionLon = serviceStation.getPositionLon();
		String stationLonLat = positionLon + "," + positionLat;
		// 查询订单照片列表
		List<Map<String, Object>> picList = uploadPicturesDao.getPicturesList(new HashMap<String, Object>() {
			private static final long serialVersionUID = 1L;
			{
				put("orderId", orderId);
			}
		});
		boolean outRange = false;// 是否超出距离
		if (CollectionUtils.isEmpty(picList)) {
			return BaseResponse.error("请先上传维修前照片！");
		}
		for (Map<String, Object> dataMap : picList) {
			Float locLon = MapUtils.getFloat(dataMap, "LocLon");
			Float locLat = MapUtils.getFloat(dataMap, "LocLat");
			String FaultLonLat = locLon + "," + locLat;
			Double distance = GetDistance.getLineDistance(stationLonLat, FaultLonLat,0);
			if (distance > serviceScope) {
				outRange = true;
				param.put("outDistance", Math.round((distance.doubleValue() - serviceScope)*100d)/100d);
				break;
			}
		}
		if (!outRange) {
			return BaseResponse.error("该工单没有超出距离限制，无需发起超距离服务申请！");
		}

		List<Map<String, Object>> causes = dictionariesTDao.getDictionariesListByDTableName("OutRangeCause");
		for (Map<String, Object> cause : causes) {
			if (causeId.equals(cause.get("ID").toString())) {
				if ("9".equals(cause.get("DInt").toString()) && StringUtils.isBlank(otherRemark)) {// 其他
					return BaseResponse.error("请填写其他原因说明！");
				}
				return BaseResponse.success();
			}
		}
		return BaseResponse.error("超距离服务原因非法！");
	}

	@Override
	@Transactional
	public BaseResponse modifyOutRangeApply(JSONObject param) {
		BaseResponse checkResult = checkBeforeModifyOutRangeApply(param);
		if (!checkResult.isSuccess()) {
			return checkResult;
		}
		UserT userT = UserThreadLocal.get();
//		1、后台控制当前工单状态、是否已经存在申请
//		2、更新申请表的信息以及版本id
//		3、更新超范围服务申请操作记录表、超范围服务负责人表更新时间
		Long orderId = param.getLong("orderId");// 工单id
		Long causeId = param.getLong("causeId");// 原因枚举Id
		String otherRemark = param.containsKey("otherRemark") ? param.getString("otherRemark") : "";// 其他原因说明（其他原因时必须）
		String pics = param.getJSONArray("pics").toJSONString();// 照片地址数组
		int version = param.getIntValue("version");// 版本号
		OutRangeT outRangeT = outRangeTDao.getOutRangeTByOrderId(orderId);
		outRangeT.setOrderId(orderId);
		outRangeT.setCauseId(causeId);
		outRangeT.setOtherRemark(otherRemark);
		outRangeT.setPicUrls(pics);
		outRangeT.setVersion(version);
		outRangeT.setUpdator(userT.getId());
		outRangeT.setUpdateTime(LocalTimeUtil.getRealCurrentTime());
		int count = outRangeTDao.updateSelective(outRangeT);
		if (count == 0) {
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			return BaseResponse.error("该申请已被处理，请刷新页面！");
		}
		OutRangeFlow outRangeFlow = new OutRangeFlow();
		outRangeFlow.setOutRangeId(outRangeT.getId());// 超范围服务申请表ID
		outRangeFlow.setUpdator(userT.getId());
		outRangeFlow.setUpdateTime(LocalTimeUtil.getRealCurrentTime());
		outRangeFlowDao.updateSelective(outRangeFlow);
		OutRangePrincipal outRangePrincipal = new OutRangePrincipal();
		outRangePrincipal.setOutRangeId(outRangeT.getId());// 超范围服务申请表ID
		outRangePrincipal.setUpdator(userT.getId());
		outRangePrincipal.setUpdateTime(LocalTimeUtil.getRealCurrentTime());
		outRangePrincipalDao.updateSelective(outRangePrincipal);
		return BaseResponse.success("修改成功！");
	}

	private BaseResponse checkBeforeModifyOutRangeApply(JSONObject param) {
		if (!param.containsKey("orderId") || !param.containsKey("causeId") || !param.containsKey("version")) {
			return BaseResponse.error("缺少必要参数！");
		}
		Long orderId = param.getLong("orderId");// 工单id
//		1、后台控制当前工单状态、是否已经存在申请
//		2、更新申请表的信息以及版本id
//		3、更新超范围服务申请操作记录表、超范围服务负责人表更新时间
		WorkOrderT workOrder = workOrderTDao.getWorkOrderByOrderId(orderId);
		if (workOrder == null) {
			return BaseResponse.error("未找到该工单信息！");
		}
		int orderStatus = workOrder.getOrderStatus();// OrderStatus=38电子围栏审批中
		if (orderStatus != 38) {
			return BaseResponse.error("该工单已处理，当前状态无法进行修改！");
		}
		
		OutRangeT outRangeT = outRangeTDao.getOutRangeTByOrderId(workOrder.getId());
		if (outRangeT == null) {
			return BaseResponse.error("该工单不存在超距离服务申请，无法发起修改申请！");
		}
		if (outRangeT.getStatus() > 10) {// 状态不为‘待一网站长审核’
			return BaseResponse.error("该申请已处理，当前状态无法进行修改！");
		}
		UserT userT = UserThreadLocal.get();
		if (userT.getId() != outRangeT.getCreator()) {
			return BaseResponse.error("只能修改本人提交的申请！");
		}
		String causeId = param.getString("causeId");// 原因枚举Id
		String otherRemark = param.getString("otherRemark");// 其他原因说明（其他原因时必须）
//		String pics = param.getJSONArray("pics").toJSONString();// 照片地址数组
		List<Map<String, Object>> causes = dictionariesTDao.getDictionariesListByDTableName("OutRangeCause");
		for (Map<String, Object> cause : causes) {
			if (causeId.equals(cause.get("ID").toString())) {
				if ("9".equals(cause.get("DInt").toString()) && StringUtils.isBlank(otherRemark)) {// 其他
					return BaseResponse.error("请填写其他原因说明！");
				}
				return BaseResponse.success();
			}
		}
		return BaseResponse.error("超距离服务原因非法！");
	}

	@Override
	public BaseResponse getOutRangeApplyList(JSONObject param) {
//		roleType登录角色（必填）3 服务站长4 服务经理
//		serchType查询类别非必须 1、 待站长审批（站长默认）2、 待服务经理审批（服务经理默认）3、 审批通过4、 已拒绝
//		pageNum 页码 非必须 默认1
//		pageSize 查询条数 非必须 默认10
		// 跟产品经理朝晨讨论后，审批通过和已拒绝的，不管是否是自己经手的，只要是有审批权限的都默认查询出来。
		if (!param.containsKey("roleType")) {
			return BaseResponse.error("缺少必要参数！");
		}
		int roleType = param.getIntValue("roleType");
		if (roleType != Dictionaries.roleType_03.getIndex() && roleType != Dictionaries.roleType_04.getIndex()) {
			return BaseResponse.error("非法的角色！");
		}
		int serchType = param.containsKey("serchType") ? param.getIntValue("serchType") : 0;
		if (serchType < 0 || serchType > 4) {
			return BaseResponse.error("非法的查询类别！");
		}
		String keyword = param.containsKey("keyword") ? param.getString("keyword") : null;
		int pageNum = param.containsKey("pageNum") ? param.getIntValue("pageNum") : 1;
//		int pageSize = param.containsKey("pageSize") ? param.getIntValue("pageSize") : 10;
		int pageSize = Integer.valueOf(this.propertiesUtils.getPropertiesValue("pagesize"));
		PageHelper.startPage(pageNum, pageSize);
		UserT userT = UserThreadLocal.get();
		List<Map<String, Object>> list = outRangeTDao.selectOutRangeApplyList(userT.getId(), roleType, serchType,
				keyword);
		return BaseResponse.success(new PageInfo<>(list));
	}

	@Override
	public BaseResponse getOutRangeApplyMsg(Long outRangeId) {
		if (outRangeId == null) {
			return BaseResponse.error("缺少必要参数！");
		}
		OutRangeT outRangeT = outRangeTDao.selectById(outRangeId);
		if (outRangeT == null) {
			return BaseResponse.error("不存在的超距离服务申请！");
		}
		JSONObject data = new JSONObject();
		data.put("orderId", outRangeT.getOrderId());
		data.put("causeId", outRangeT.getCauseId());

		List<Map<String, Object>> causes = dictionariesTDao.getDictionariesListByDTableName("OutRangeCause");
		for (Map<String, Object> cause : causes) {
			if (outRangeT.getCauseId() == Long.valueOf(cause.get("ID").toString()).longValue()) {
				data.put("cause", cause.get("DValue").toString());
				break;
			}
		}
		data.put("causeId", outRangeT.getCauseId());
		data.put("otherRemark", outRangeT.getOtherRemark());
		data.put("version", outRangeT.getVersion());
		data.put("statusValue", outRangeT.getStatus());
		data.put("status", outRangeT.genStatus());
		try {
			data.put("pics", JSONArray.parse(outRangeT.getPicUrls()));
		} catch (Exception e) {
		}
		return BaseResponse.success(data);
	}

	@Override
	public BaseResponse getOutRangeApplyProcess(Long outRangeId) {
		if (outRangeId == null) {
			return BaseResponse.error("缺少必要参数！");
		}
		OutRangeT outRangeT = outRangeTDao.selectById(outRangeId);
		if (outRangeT == null) {
			return BaseResponse.error("不存在的超距离服务申请！");
		}
		StringBuilder query = new StringBuilder();
		query.append(" select");
		query.append(" case when flow.NextStatus = 10 then '服务技师'");
		query.append(" when flow.NextStatus = 20 or flow.NextStatus = 40 then '服务站长'");
		query.append(" else '服务经理' end roleTypeName,");
		query.append(" u.Contact userName,");
		query.append(" u.Phone phone,");
		query.append(" flow.Action action,");
		query.append(" flow.NextStatus nextStatus,");
		query.append(" coalesce(flow.UpdateTime,flow.CreateTime) createTime,");
		query.append(" flow.Opinion opinion");
		query.append(" from OutRangeFlow_T flow");
		query.append(" inner join User_T u");
		query.append(" on flow.Creator = u.ID");
		query.append(" where flow.OutRangeId = %d and flow.Flag = 0");
		query.append(" order by flow.CreateTime desc");
		return BaseResponse.success(outRangeFlowDao.findBySQL(String.format(query.toString(), outRangeId)));
	}

	@Override
	@Transactional
	public BaseResponse submitOutRangeApprove(JSONObject param, HttpServletRequest request,
			HttpServletResponse response) {
		BaseResponse checkResult = checkBeforesubmitOutRangeApprove(param);
		if (!checkResult.isSuccess()) {
			return checkResult;
		}
		UserT userT = UserThreadLocal.get();
//		1、判断工单状态、当前申请状态
//		2、更新：超范围服务申请表状态、超范围服务负责人表的申请表状态
//		3、插入：超范围服务申请操作记录表、超范围服务负责人表
//		4、审批不通过，更新工单表的异常关闭原因以及状态
//		outRangeId	申请ID（必填）
//		action	审批结论（2、审批通过3、审批不通过）
//		opinion	审批意见
//		version	版本号
		Long outRangeId = param.getLong("outRangeId");// 申请ID
		int action = param.getIntValue("action");// 审批结论（2、审批通过3、审批不通过）
		int version = param.getIntValue("version");// 版本号
		String opinion = param.getString("opinion");// 审批意见
		// 更新超范围服务申请表
		OutRangeT outRangeT = outRangeTDao.selectById(outRangeId);
		outRangeT.setVersion(version);
		outRangeT.setUpdator(userT.getId());
		outRangeT.setUpdateTime(LocalTimeUtil.getRealCurrentTime());
		int status = outRangeT.getStatus();// 申请状态标记10、待一网站长审核20、待区域经理审核30、终审通过40、一网站长审核不通过50、区域经理审核不通过
		switch (status) {
		case 10:// 10、待一网站长审核
			outRangeT.setStatus(action == 2 ? 20 : 40);
			break;
		case 20:// 20、待区域经理审核
			outRangeT.setStatus(action == 2 ? 30 : 50);
			break;
		default:
			break;
		}
		int count = outRangeTDao.updateSelective(outRangeT);
		if (count == 0) {
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			return BaseResponse.error("该申请已被处理，请刷新页面！");
		}
		// 更新超范围服务负责人表的flag = -1
		OutRangePrincipal outRangePrincipal = new OutRangePrincipal();
		outRangePrincipal.setOutRangeId(outRangeT.getId());// 超范围服务申请表ID
		outRangePrincipal.setFlag(-1);
		outRangePrincipal.setUpdator(userT.getId());
		outRangePrincipal.setUpdateTime(LocalTimeUtil.getRealCurrentTime());
		outRangePrincipalDao.updateSelective(outRangePrincipal);
		// 插入超范围服务申请操作记录表
		OutRangeFlow outRangeFlow = new OutRangeFlow();
		outRangeFlow.setOutRangeId(outRangeT.getId());// 超范围服务申请表ID
		outRangeFlow.setAction(action);// 行为动作1、提交申请2、审批通过3、审批不通过
		outRangeFlow.setOpinion(opinion);
		outRangeFlow.setNextStatus(outRangeT.getStatus());// 操作后的申请状态标记
		outRangeFlow.setFlag(0);
		outRangeFlow.setCreator(userT.getId());
		outRangeFlow.setCreateTime(LocalTimeUtil.getRealCurrentTime());
		outRangeFlowDao.insertSelective(outRangeFlow);
		// 一网站长审批通过，插入超范围服务负责人表
		WorkOrderT workOrder = workOrderTDao.getWorkOrderByOrderId(outRangeT.getOrderId());
		if (action == 2) {
			if (status == 10) {
				Map<String, Object> map = new HashMap<>();
				map.put("ServiceStationID", workOrder.getServiceStationId());
				map.put("CompanyID", workOrder.getOrderChannel());
				List<PositionUserT> positionUserTList = positionUserTDao
						.getPostUserTListByServiceStationIdCompanyId(map);
				positionUserTList.addAll(positionUserTDao.getPostUserTListByChildStationIdCompanyId(map));
				for (PositionUserT positionUserT : positionUserTList) {
					OutRangePrincipal principal = new OutRangePrincipal();
					principal.setOrderId(outRangeT.getOrderId());// 工单ID
					principal.setOutRangeId(outRangeT.getId());// 超范围服务申请表ID
					principal.setOutRangeStatus(20);// 申请状态标记10、待一网站长审核20、待区域经理审核30、终审通过40、一网站长审核不通过50、区域经理审核不通过
					principal.setPrincipalId(positionUserT.getUserID());// 负责人Id
					principal.setFlag(0);
					principal.setCreator(userT.getId());
					principal.setCreateTime(LocalTimeUtil.getRealCurrentTime());
					outRangePrincipalDao.insertSelective(principal);

					// 一网站长审批通过给区域经理发送短信提醒
					String smsText = "您有新的超距离审批提醒，工单号：%s，正在等待服务经理审批";
					// 'Function',28,'电子围栏申请状态变更提醒'
					// 'Category',6,'提交申请提醒'
					// 'Category',7,'审批通过提醒'
					// 'Category',8,'审批拒绝提醒'
					// 'Category',9,'已失效提醒'
					noticeService.sendSMS(28, 7, outRangeT.getOrderId(), positionUserT.getUserID(), null,
							String.format(smsText, workOrder.getOrderNo()), userT.getId());
				}
				return BaseResponse.success("审核已通过，待服务经理审批!");
			} else if (status == 20) {// 终审通过将工单状态变回技师已接单
				workOrder.setOrderStatus(8);// 8 技师已接单
				workOrder.setUpdator(userT.getId());
				workOrder.setUpdateTime(LocalTimeUtil.getRealCurrentTime());
				workOrderTDao.updateWorkOrderById(workOrder);

				// 服务经理审批通过给技师发送短信提醒
				String smsText = "您的超距离审批已通过，工单号：%s，可以继续维修，请查看。";
				// 'Function',28,'电子围栏申请状态变更提醒'
				// 'Category',6,'提交申请提醒'
				// 'Category',7,'审批通过提醒'
				// 'Category',8,'审批拒绝提醒'
				// 'Category',9,'已失效提醒'
				noticeService.sendSMS(28, 7, outRangeT.getOrderId(), outRangeT.getCreator(), null,
						String.format(smsText, workOrder.getOrderNo()), userT.getId());
			}
		} else if (action == 3) {// 审批不通过，更新工单表的异常关闭原因以及状态
			// 调用异常关闭的Service，传参
//			ID	工单id(工单表主键id) (必传)
//			CloseReason	关闭工单原因(必传)
//			serviceStationId	服务站id(不加密必传)
//			LocLon	经度(必传)
//			LocLat	纬度(必传)
//			Location	故障地点(必传)
//			IMEI	手机串号(必传)
//			updateTime	工单上一次修改时间
			// 经纬度和手机串号故障地点就从维修前上传的照片信息最后一条数据中获取
			WorkOrderPics pic = workOrderPicsDao.selectOneByOrderId(outRangeT.getOrderId());
			Map<String, Object> closeWorkOrderMap = new HashMap<>();
			closeWorkOrderMap.put("response", response);
			closeWorkOrderMap.put("request", request);
			closeWorkOrderMap.put("ID", outRangeT.getOrderId() + "");
//			closeWorkOrderMap.put("CloseReason", "超距离服务申请未通过异常关闭");
			closeWorkOrderMap.put("CloseReason", opinion);// 其中（异常关闭原因）需要更新为超距离审批时拒绝的原因
			closeWorkOrderMap.put("serviceStationId", workOrder.getServiceStationId() + "");
			closeWorkOrderMap.put("updateTime", workOrder.getUpdateTime());
			closeWorkOrderMap.put("LocLon", pic.getLocLon() + "");
			closeWorkOrderMap.put("LocLat", pic.getLocLat() + "");
			closeWorkOrderMap.put("Location", pic.getLocation());
			closeWorkOrderMap.put("IMEI", pic.getIMEI());
			BaseResponse rs = workOrderTService.updateCloseWorkOrderById(closeWorkOrderMap);
			if (!rs.isSuccess()) {
				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
				return rs;
			}

			// 审批不通过给技师发送短信提醒
			String smsText = "您有超距离审批未通过，原因：%s，工单号：%s，请查看";
			// 'Function',28,'电子围栏申请状态变更提醒'
			// 'Category',6,'提交申请提醒'
			// 'Category',7,'审批通过提醒'
			// 'Category',8,'审批拒绝提醒'
			// 'Category',9,'已失效提醒'
			noticeService.sendSMS(28, 8, outRangeT.getOrderId(), outRangeT.getCreator(), null,
					String.format(smsText, opinion, workOrder.getOrderNo()), userT.getId());
		}
		return BaseResponse.success();
	}

	private BaseResponse checkBeforesubmitOutRangeApprove(JSONObject param) {
//		1、判断工单状态、当前申请状态
//		2、更新：超范围服务申请表状态、超范围服务负责人表的Flag=-1
//		3、插入：超范围服务申请操作记录表、超范围服务负责人表
//		4、审批不通过，更新工单表的异常关闭原因以及状态
//		outRangeId	申请ID（必填）
//		action	审批结论（2、审批通过3、审批不通过）
//		opinion	审批意见
//		version	版本号
		if (!param.containsKey("outRangeId") || !param.containsKey("action") || !param.containsKey("version")) {
			return BaseResponse.error("缺少必要参数！");
		}
		Long outRangeId = param.getLong("outRangeId");// 申请ID
		int action = param.getIntValue("action");// 审批结论（2、审批通过3、审批不通过）
		if (action != 2 && action != 3) {
			return BaseResponse.error("非法的审批结论！");
		}
		if (action == 3 && !param.containsKey("opinion")) {
			return BaseResponse.error("请填写不通过原因！");
		}
//		int version = param.getIntValue("version");// 版本号
		OutRangeT outRangeT = outRangeTDao.selectById(outRangeId);
		if (outRangeT == null) {
			return BaseResponse.error("找不到该申请信息！");
		}
		int status = outRangeT.getStatus();
		// 申请状态标记10、待一网站长审核20、待区域经理审核30、终审通过40、一网站长审核不通过50、区域经理审核不通过60、已失效
		if (status != 10 && status != 20) {
			return BaseResponse.error("该申请已处理，当前状态无法进行审批操作！");
		}
		WorkOrderT workOrder = workOrderTDao.getWorkOrderByOrderId(outRangeT.getOrderId());
		if (workOrder == null) {
			return BaseResponse.error("未找到该工单信息！");
		}
		int orderStatus = workOrder.getOrderStatus();// OrderStatus=38电子围栏审批中
		if (orderStatus != 38) {
			return BaseResponse.error("该工单已处理，当前状态无法进行审批！");
		}
		UserT userT = UserThreadLocal.get();
		List<Object> params = new ArrayList<>();
		StringBuilder countSQL = new StringBuilder();
		countSQL.append(" select count(*)");
		countSQL.append(" from OutRangePrincipal_T");
		countSQL.append(" where Flag = 0");
		countSQL.append(" and OutRangeId = %d");
		params.add(outRangeId);
		countSQL.append(" and OutRangeStatus = %d");
		params.add(status);
		countSQL.append(" and PrincipalId = %d");
		params.add(userT.getId());
		int count = outRangePrincipalDao.countBySQL(String.format(countSQL.toString(), params.toArray()));
		if (count == 0) {
			return BaseResponse.error("您没有审批权限！");
		}
		return BaseResponse.success();
	}

}
